package edu.hawaii.jmotif.sequitur.view;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Comparator;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.JXTableHeader;
import edu.hawaii.jmotif.sequitur.logic.MotifChartData;
import edu.hawaii.jmotif.sequitur.model.SequiturMessage;
import edu.hawaii.jmotif.sequitur.view.table.SequiturTableColumns;
import edu.hawaii.jmotif.sequitur.view.table.SequiturTableModel;

/**
 * 
 * handling the chart panel and sequitur rules table
 * 
 * @author Manfred Lerner
 * 
 */

public class SequiturRulesPanel extends JPanel implements ListSelectionListener,
    PropertyChangeListener {

  /** Fancy serial. */
  private static final long serialVersionUID = -2710973854572981568L;

  public static final String FIRING_PROPERTY = "selectedRow";

  private SequiturTableModel sequiturTableModel = new SequiturTableModel();
  private JXTable sequiturTable;

  private MotifChartData chartData;

  private JScrollPane sequiturRulesPane;

  private String selectedRule;

  private boolean acceptListEvents;

  /*
   * 
   * Comparator for the sorting of the Expanded Sequitur Rules Easy logic: sort by the length of the
   * Expanded Sequitur Rules
   */
  private Comparator<String> expandedRuleComparator = new Comparator<String>() {
    public int compare(String s1, String s2) {
      return s1.length() - s2.length();
    }
  };

  /**
   * Constructor.
   */
  public SequiturRulesPanel() {
    super();
    this.sequiturTableModel = new SequiturTableModel();
    this.sequiturTable = new JXTable() {

      private static final long serialVersionUID = 2L;

      @Override
      protected JTableHeader createDefaultTableHeader() {
        return new JXTableHeader(columnModel) {
          private static final long serialVersionUID = 1L;

          @Override
          public void updateUI() {
            super.updateUI();
            // need to do in updateUI to survive toggling of LAF
            if (getDefaultRenderer() instanceof JLabel) {
              ((JLabel) getDefaultRenderer()).setHorizontalAlignment(JLabel.CENTER);

            }
          }
        };
      }

    };
    this.sequiturTable.setModel(sequiturTableModel);
    this.sequiturTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    this.sequiturTable.setShowGrid(false);

    this.sequiturTable.getSelectionModel().addListSelectionListener(this);
    org.jdesktop.swingx.renderer.DefaultTableRenderer renderer = (org.jdesktop.swingx.renderer.DefaultTableRenderer) sequiturTable
        .getDefaultRenderer(String.class);

    // Make some columns wider than the rest, so that the info fits in.
    TableColumnModel columnModel = sequiturTable.getColumnModel();
    columnModel.getColumn(SequiturTableColumns.RULE_NUMBER.ordinal()).setPreferredWidth(20);
    columnModel.getColumn(SequiturTableColumns.RULE_FREQUENCY.ordinal()).setPreferredWidth(20);
    columnModel.getColumn(SequiturTableColumns.RULE_INTERVALS_SD.ordinal()).setPreferredWidth(20);
    columnModel.getColumn(SequiturTableColumns.RULE_AVERAGE_PERIOD.ordinal()).setPreferredWidth(20);
    columnModel.getColumn(SequiturTableColumns.RULE_AVERAGE_MOTIF_LENGTH.ordinal()).setPreferredWidth(20);
    columnModel.getColumn(SequiturTableColumns.SEQUITUR_RULE.ordinal()).setPreferredWidth(80);
    columnModel.getColumn(SequiturTableColumns.EXPANDED_SEQUITUR_RULE.ordinal()).setPreferredWidth(
        640);

    TableRowSorter<SequiturTableModel> sorter = new TableRowSorter<SequiturTableModel>(
        sequiturTableModel);
    sequiturTable.setRowSorter(sorter);
    sorter.setComparator(SequiturTableColumns.EXPANDED_SEQUITUR_RULE.ordinal(),
        expandedRuleComparator);

    this.sequiturRulesPane = new JScrollPane(sequiturTable);
  }

  /**
   * Set the new data.
   * 
   * @param chartData the new data.
   */
  public void set(MotifChartData chartData) {

    this.acceptListEvents = false;

    // save the data
    this.chartData = chartData;

    // update
    sequiturTableModel.update(this.chartData.getCurrentRule().getSAXContainerList());

    // put new data on show
    resetPanel();

    this.acceptListEvents = true;
  }

  /**
   * create the panel with the sequitur rules table
   * 
   * @return sequitur panel
   */
  private void resetPanel() {
    // cleanup all the content
    this.removeAll();
    this.add(sequiturRulesPane);
    this.validate();
    this.repaint();
  }

  /**
   * @return sequitur table model
   */
  public SequiturTableModel getSequiturTableModel() {
    return sequiturTableModel;
  }

  /**
   * @return sequitur table
   */
  public JTable getSequiturTable() {
    return sequiturTable;
  }

  @Override
  public void valueChanged(ListSelectionEvent arg) {
    if (!arg.getValueIsAdjusting() && this.acceptListEvents) {
      int col = sequiturTable.getSelectedColumn();
      int row = sequiturTable.getSelectedRow();
      System.out.println("ROW: " + row + " - COL: " + col);
      String rule = (String) sequiturTable.getValueAt(row,
          SequiturTableColumns.EXPANDED_SEQUITUR_RULE.ordinal());
      this.firePropertyChange(FIRING_PROPERTY, this.selectedRule, rule);
      this.selectedRule = rule;
    }
  }

  public void propertyChange(PropertyChangeEvent event) {
    String prop = event.getPropertyName();

    if (prop.equalsIgnoreCase(SequiturMessage.MAIN_CHART_CLICKED_MESSAGE)) {
      String rule = (String) event.getNewValue();
      for (int row = 0; row <= sequiturTable.getRowCount() - 1; row++) {
        for (int col = 0; col <= sequiturTable.getColumnCount() - 1; col++) {
          if (rule.equals(chartData.convert2OriginalSAXAlphabet('1',
              sequiturTable.getValueAt(row, col).toString()))) {
            sequiturTable.scrollRectToVisible(sequiturTable.getCellRect(row, 0, true));
            sequiturTable.setRowSelectionInterval(row, row);
          }
        }
      }
    }
  }

}
